﻿using System;
using System.Collections.Generic;
using System.IO;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using HYElectricSetting;

namespace ElectricDim
{
	[Transaction(TransactionMode.Manual)]
	public class CmdGroundingDim : IExternalCommand
	{
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			UIDocument activeUIDocument = commandData.Application.ActiveUIDocument;
			Document document = activeUIDocument.Document;
			GroundingWireFilter groundingWireFilter = new GroundingWireFilter();
			IList<Reference> list = null;
			try
			{
				list = activeUIDocument.Selection.PickObjects((Autodesk.Revit.UI.Selection.ObjectType)1, groundingWireFilter, "请选择接地线（详图线）");
				if (list == null)
				{
					return Autodesk.Revit.UI.Result.Failed;
				}
			}
			catch
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			FamilySymbol familySymbol = this.LoadFamliyEarthPole(document);
			FamilySymbol familySymbol2 = this.LoadFamilyOblique(document);
			if (familySymbol2 == null || familySymbol == null)
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			foreach (Reference reference in list)
			{
				DetailCurve detailCurve = document.GetElement(reference) as DetailCurve;
				this.DeleteOldMark(detailCurve, document);
			}
			foreach (Reference reference2 in list)
			{
				DetailCurve detailCurve2 = document.GetElement(reference2) as DetailCurve;
				if (!detailCurve2.GeometryCurve.IsCyclic || detailCurve2.GeometryCurve.IsBound)
				{
					if (detailCurve2 is DetailLine)
					{
						DetailLine detailLine = detailCurve2 as DetailLine;
						this.LayoutEarthPole(detailLine, document, familySymbol, familySymbol2);
					}
					else
					{
						DetailArc detailArc = detailCurve2 as DetailArc;
						this.LayoutEarthPole(detailArc, document, familySymbol, familySymbol2);
					}
				}
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private FamilySymbol LoadFamilyOblique(Autodesk.Revit.DB.Document doc)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(Family));
			if (filteredElementCollector != null)
			{
				foreach (Element element in filteredElementCollector.ToElements())
				{
					Family family = element as Family;
					if (family.Name.CompareTo("接地线-斜线") == 0)
					{
						foreach (FamilySymbol familySymbol in family.GetSymbols())
						{
							if (familySymbol.Name == "0")
							{
								return familySymbol;
							}
						}
					}
				}
			}
			try
			{
				FileInfo fileInfo = null;
				foreach (FamilySymbol familySymbol2 in ElectricMark.GroundingLineMark(doc)[0].Load(doc, ref fileInfo).GetSymbols())
				{
					if (familySymbol2.Name == "0")
					{
						return familySymbol2;
					}
				}
			}
			catch
			{
				YJKMessageBox.Show("加载斜短线族失败!");
			}
			return null;
		}

		private FamilySymbol LoadFamliyEarthPole(Autodesk.Revit.DB.Document doc)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(Family));
			if (filteredElementCollector != null)
			{
				foreach (Element element in filteredElementCollector.ToElements())
				{
					Family family = element as Family;
					if (family.Name.CompareTo("接地线-接地极") == 0)
					{
						return family.GetSymbols()[0];
					}
				}
			}
			try
			{
				FileInfo fileInfo = null;
				return ElectricMark.GroundingPoleMark(doc)[0].Load(doc, ref fileInfo).GetSymbols()[0];
			}
			catch
			{
				YJKMessageBox.Show("加载接地极族失败!");
			}
			return null;
		}

		private void DeleteOldMark(DetailCurve detailCurve, Autodesk.Revit.DB.Document doc)
		{
			Curve geometryCurve = detailCurve.GeometryCurve;
			double z = geometryCurve.GetEndPoint(0).Z;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, doc.ActiveView.Id);
			filteredElementCollector.OfClass(typeof(FamilyInstance));
			if (filteredElementCollector != null)
			{
				Transaction transaction = new Transaction(doc, "DeleteClamp");
				transaction.Start();
				try
				{
					foreach (Element element in filteredElementCollector.ToElements())
					{
						FamilyInstance familyInstance = element as FamilyInstance;
						Family family = familyInstance.Symbol.Family;
						XYZ point = (familyInstance.Location as LocationPoint).Point;
						XYZ xyz = new XYZ(point.X, point.Y, z);
						if ((family.Name.CompareTo("接地线-接地极") == 0 || family.Name.CompareTo("接地线-斜线") == 0) && geometryCurve.Distance(xyz) <= 0.001)
						{
							doc.Delete(element.Id);
						}
					}
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
			}
		}

		private void LayoutEarthPole(DetailLine detailLine, Autodesk.Revit.DB.Document doc, FamilySymbol fsEarthPole, FamilySymbol fsOblique)
		{
			Curve geometryCurve = detailLine.GeometryCurve;
			double length = geometryCurve.Length;
			Transaction transaction = new Transaction(doc, "NewEarthPole");
			transaction.Start();
			try
			{
				int num = Convert.ToInt32(Math.Floor(length / this.m_dGap));
				double num2 = (length - (double)(num - 1) * this.m_dGap) * 0.5;
				XYZ endPoint = geometryCurve.GetEndPoint(0);
				XYZ endPoint2 = geometryCurve.GetEndPoint(1);
				XYZ xyz = (endPoint2 - endPoint).Normalize();
				XYZ xyz2 = endPoint;
				for (int i = 0; i < num; i++)
				{
					XYZ xyz3 = endPoint + xyz * (num2 + this.m_dGap * (double)i);
					UnifiedModified.ActivateFamilySymbol(fsEarthPole);
					doc.Create.NewFamilyInstance(xyz3, fsEarthPole, doc.ActiveView);
					Line line = Line.CreateBound(xyz2, xyz3);
					this.LayoutOblique(line, doc, fsOblique);
					xyz2 = xyz3;
				}
				Line line2 = Line.CreateBound(xyz2, endPoint2);
				this.LayoutOblique(line2, doc, fsOblique);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private void LayoutEarthPole(DetailArc detailArc, Autodesk.Revit.DB.Document doc, FamilySymbol fsEarthPole, FamilySymbol fsOblique)
		{
			Curve geometryCurve = detailArc.GeometryCurve;
			double length = geometryCurve.Length;
			Transaction transaction = new Transaction(doc, "NewEarthPole");
			transaction.Start();
			try
			{
				int num = Convert.ToInt32(Math.Floor(length / this.m_dGap));
				double num2 = (length - (double)(num - 1) * this.m_dGap) * 0.5;
				Arc arc = geometryCurve as Arc;
				XYZ endPoint = geometryCurve.GetEndPoint(0);
				XYZ endPoint2 = geometryCurve.GetEndPoint(1);
				XYZ center = arc.Center;
				double radius = arc.Radius;
				double num3 = num2 / radius;
				double num4 = this.m_dGap / radius;
				XYZ normal = arc.Normal;
				XYZ ptStart = endPoint;
				for (int i = 0; i < num; i++)
				{
					XYZ xyz = Transform.CreateRotationAtPoint(normal, num3 + num4 * (double)i, center).OfPoint(endPoint);
					UnifiedModified.ActivateFamilySymbol(fsEarthPole);
					doc.Create.NewFamilyInstance(xyz, fsEarthPole, doc.ActiveView);
					Arc arc2 = this.CreateArc(ptStart, xyz, center, normal);
					this.LayoutOblique(arc2, doc, fsOblique);
					ptStart = xyz;
				}
				Arc arc3 = this.CreateArc(ptStart, endPoint2, center, normal);
				this.LayoutOblique(arc3, doc, fsOblique);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
		}

		private void LayoutOblique(Line line, Autodesk.Revit.DB.Document doc, FamilySymbol fsOblique)
		{
			double length = line.Length;
			SubTransaction subTransaction = new SubTransaction(doc);
			subTransaction.Start();
			try
			{
				int num = Convert.ToInt32(Math.Floor(length / this.m_dGapOblique));
				double num2 = (length - (double)(num - 1) * this.m_dGapOblique) * 0.5;
				XYZ endPoint = line.GetEndPoint(0);
				XYZ xyz = (line.GetEndPoint(1) - endPoint).Normalize();
				double num3 = XYZ.BasisX.AngleOnPlaneTo(xyz, XYZ.BasisZ);
				for (int i = 0; i < num; i++)
				{
					XYZ xyz2 = endPoint + xyz * (num2 + this.m_dGapOblique * (double)i);
					UnifiedModified.ActivateFamilySymbol(fsOblique);
					FamilyInstance familyInstance = doc.Create.NewFamilyInstance(xyz2, fsOblique, doc.ActiveView);
					Line line2 = Line.CreateBound(xyz2, xyz2 + XYZ.BasisZ);
					ElementTransformUtils.RotateElement(doc, familyInstance.Id, line2, num3);
				}
				subTransaction.Commit();
			}
			catch
			{
				subTransaction.RollBack();
			}
		}

		private void LayoutOblique(Arc arc, Autodesk.Revit.DB.Document doc, FamilySymbol fsOblique)
		{
			double length = arc.Length;
			SubTransaction subTransaction = new SubTransaction(doc);
			subTransaction.Start();
			try
			{
				int num = Convert.ToInt32(Math.Floor(length / this.m_dGapOblique));
				double num2 = (length - (double)(num - 1) * this.m_dGapOblique) * 0.5;
				XYZ endPoint = arc.GetEndPoint(0);
				XYZ center = arc.Center;
				double radius = arc.Radius;
				double num3 = num2 / radius;
				double num4 = this.m_dGapOblique / radius;
				XYZ normal = arc.Normal;
				for (int i = 0; i < num; i++)
				{
					XYZ xyz = Transform.CreateRotationAtPoint(normal, num3 + num4 * (double)i, center).OfPoint(endPoint);
					UnifiedModified.ActivateFamilySymbol(fsOblique);
					FamilyInstance familyInstance = doc.Create.NewFamilyInstance(xyz, fsOblique, doc.ActiveView);
					double num5 = XYZ.BasisX.AngleOnPlaneTo(xyz - center, XYZ.BasisZ);
					Line line = Line.CreateBound(xyz, xyz + XYZ.BasisZ);
					ElementTransformUtils.RotateElement(doc, familyInstance.Id, line, num5);
				}
				subTransaction.Commit();
			}
			catch
			{
				subTransaction.RollBack();
			}
		}

		private Arc CreateArc(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal)
		{
			XYZ xyz = this.CalculatMidPoint(ptStart, ptEnd, ptCenter, normal);
			return Arc.Create(ptStart, ptEnd, xyz);
		}

		private XYZ CalculatMidPoint(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal)
		{
			XYZ xyz = ptStart - ptCenter;
			XYZ xyz2 = ptEnd - ptCenter;
			double num = xyz.AngleTo(xyz2) / 2.0;
			return Transform.CreateRotationAtPoint(normal, num, ptCenter).OfPoint(ptStart);
		}

		private double m_dGap = (double)ElectricSettingDataAssist.GetGroundingPoleSpacing(5000) / 304.8;

		private double m_dGapOblique = 3.9370078740157477;
	}
}
